<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ndXew" id="ndXew"><span data-lake-id="u5b6fd49b" id="u5b6fd49b">典型回答</span></h1>
  <p data-lake-id="ud407be1c" id="ud407be1c"><span data-lake-id="u2202ad29" id="u2202ad29">在Java中，共有四种方式可以创建线程，分别是</span></p>
  <ul list="ua84ba618">
   <li fid="u325c8f05" data-lake-id="u382e3456" id="u382e3456"><span data-lake-id="u174d401f" id="u174d401f">继承</span><strong><span data-lake-id="u2185014f" id="u2185014f">Thread</span></strong><span data-lake-id="u14a885ed" id="u14a885ed">类创建线程</span></li>
   <li fid="u325c8f05" data-lake-id="uf51d9682" id="uf51d9682"><span data-lake-id="u8d608dde" id="u8d608dde">实现</span><strong><span data-lake-id="u43aa9f62" id="u43aa9f62">Runnable</span></strong><span data-lake-id="ua87b2005" id="ua87b2005">接口创建线程</span></li>
   <li fid="u325c8f05" data-lake-id="u616b8c08" id="u616b8c08"><span data-lake-id="u62ad5b4f" id="u62ad5b4f">通过</span><strong><span data-lake-id="u7a3f0baa" id="u7a3f0baa">Callable和FutureTask</span></strong><span data-lake-id="u89376016" id="u89376016">创建线程</span></li>
   <li fid="u325c8f05" data-lake-id="ua23bb62b" id="ua23bb62b"><span data-lake-id="ud0daa639" id="ud0daa639">通过</span><strong><span data-lake-id="u6b639e7c" id="u6b639e7c">线程池</span></strong><span data-lake-id="u25ef990e" id="u25ef990e">创建线程</span></li>
  </ul>
  <p data-lake-id="u3d542057" id="u3d542057"><span data-lake-id="u237fb493" id="u237fb493">​</span><br></p>
  <blockquote data-lake-id="uf0fd5143" id="uf0fd5143">
   <p data-lake-id="uffc3d9ed" id="uffc3d9ed"><span data-lake-id="u4ac496c1" id="u4ac496c1">其实，归根结底最终就两种，一个是继承</span><strong><span data-lake-id="u60c3e628" id="u60c3e628">Thread</span></strong><span data-lake-id="u71a617c2" id="u71a617c2">类，一个是实现</span><strong><span data-lake-id="u0a0a9c99" id="u0a0a9c99">Runnable</span></strong><span data-lake-id="ucfedcff4" id="ucfedcff4">接口，至于其他的。也是基于这两个方式实现的。但是有的时候面试官更关注的是实际写代码过程中，有几种方式可以实现。所以一般回答4种也没啥毛病。</span></p>
  </blockquote>
  <p data-lake-id="u468b0ea4" id="u468b0ea4"><br></p>
  <h1 data-lake-id="Ks3gi" id="Ks3gi"><span data-lake-id="u90637f35" id="u90637f35">扩展知识</span></h1>
  <h2 data-lake-id="DszHh" id="DszHh"><span data-lake-id="uf578d7a2" id="uf578d7a2">Runnable和Callable区别</span></h2>
  <p data-lake-id="u52cc22d5" id="u52cc22d5"><br></p>
  <p data-lake-id="u9ff9dbaa" id="u9ff9dbaa"><span data-lake-id="u2c9b60a6" id="u2c9b60a6">Runnable接口和Callable接口都可以用来创建新线程，实现Runnable的时候，需要实现run方法；实现Callable接口的话，需要实现call方法。</span></p>
  <p data-lake-id="ub984c036" id="ub984c036"><span data-lake-id="u8eb52d2d" id="u8eb52d2d">​</span><br></p>
  <p data-lake-id="u7eb5c6f1" id="u7eb5c6f1"><strong><span data-lake-id="u73885dd1" id="u73885dd1">Runnable的run方法无返回值，Callable的call方法有返回值，类型为Object</span></strong></p>
  <p data-lake-id="u20006289" id="u20006289"><span data-lake-id="ucbca31c4" id="ucbca31c4">​</span><br></p>
  <p data-lake-id="u72d07ad6" id="u72d07ad6"><span data-lake-id="u846439bf" id="u846439bf">Callable中可以够抛出checked exception,而Runnable不可以。</span></p>
  <p data-lake-id="u1fedb7ad" id="u1fedb7ad"><span data-lake-id="uaf0dfad5" id="uaf0dfad5">​</span><br></p>
  <p data-lake-id="u07aa95b5" id="u07aa95b5"><span data-lake-id="u78df404d" id="u78df404d">Callable和Runnable都可以应用于executors。而Thread类只支持Runnable。</span></p>
  <p data-lake-id="ud7468483" id="ud7468483"><span data-lake-id="ua31e7a10" id="ua31e7a10">​</span><br></p>
  <h2 data-lake-id="b21lJ" id="b21lJ"><span data-lake-id="u9b066082" id="u9b066082">Future</span></h2>
  <p data-lake-id="u5af6b412" id="u5af6b412"><br></p>
  <p data-lake-id="ub6838be2" id="ub6838be2"><span data-lake-id="u17af01f5" id="u17af01f5">Future是一个接口，代表了一个异步执行的结果。接口中的方法用来检查执行是否完成、等待完成和得到执行的结果。当执行完成后，只能通过get()方法得到结果，get方法会阻塞直到结果准备好了。如果想取消，那么调用cancel()方法。</span></p>
  <p data-lake-id="u2ab6c745" id="u2ab6c745"><br></p>
  <p data-lake-id="u1809105d" id="u1809105d"><span data-lake-id="u3076cfef" id="u3076cfef">FutureTask是Future接口的一个实现，它实现了一个可以提交给Executor执行的任务，并且可以用来检查任务的执行状态和获取任务的执行结果。</span></p>
  <p data-lake-id="uc0beafb8" id="uc0beafb8"><span data-lake-id="u68cdc9f9" id="u68cdc9f9">​</span><br></p>
  <p data-lake-id="u32d0a189" id="u32d0a189"><span data-lake-id="u468fd94e" id="u468fd94e">​</span><br></p>
  <h3 data-lake-id="slG8d" id="slG8d"><span data-lake-id="u4f8f24fe" id="u4f8f24fe">FutureTask和Callable示例</span></h3>
  <p data-lake-id="ue0f60042" id="ue0f60042"><br></p>
  <pre lang="java"><code>
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureAndCallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Callable&lt;String&gt; callable = () -&gt; {
            System.out.println("Entered Callable");
            Thread.sleep(2000);
            return "Hello from Callable";
        };

        FutureTask&lt;String&gt; futureTask = new FutureTask&lt;&gt;(callable);
        Thread thread = new Thread(futureTask);
        thread.start();

        System.out.println("Do something else while callable is getting executed");
        System.out.println("Retrieved: " + futureTask.get());
    }
}

</code></pre>
  <p data-lake-id="u3ebfc55a" id="u3ebfc55a"><br></p>
  <h1 data-lake-id="x0Oxk" id="x0Oxk"><span data-lake-id="u1384f60e" id="u1384f60e">线程池</span></h1>
  <p data-lake-id="ua0ca4c5f" id="ua0ca4c5f"><br></p>
  <p data-lake-id="u51ee5450" id="u51ee5450"><br></p>
  <h3 data-lake-id="Nkrfg" id="Nkrfg"><span data-lake-id="uaee945a5" id="uaee945a5">线程池和Callable的示例</span></h3>
  <p data-lake-id="u6665bb21" id="u6665bb21"><br></p>
  <pre lang="java"><code>
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureAndCallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Callable&lt;String&gt; callable = () -&gt; {
            System.out.println("Entered Callable");
            Thread.sleep(2000);
            return "Hello from Callable";
        };

        System.out.println("Submitting Callable");
        Future&lt;String&gt; future = executor.submit(callable);

        System.out.println("Do something else while callable is getting executed");
        System.out.println("Retrieved: " + future.get());

        executor.shutdown();
    }
}

</code></pre>
 </body>
</html>